/**
 * Copyright (c) 快宝网络 kuaidihelp.com Co., Ltd. All Rights Reserved 禁止外泄以及用于其它的商业用途
 */

import React, { useState, useCallback, useRef, useEffect } from 'react';
import { useUpdateEffect, useUnmount, usePrevious } from 'ahooks';
import { connect } from 'dva';
import moment from 'moment';
import { Row, Col, Breadcrumb, message } from 'antd';
import SwiperCore, { Navigation } from 'swiper';
import { Swiper, SwiperSlide } from 'swiper/react';
import classnames from 'classnames';
import zoom_in_1 from '@/assets/bigScreen/zoom_in_1.png';
import video_cover from '@/assets/bigScreen/video_cover.png';
import ReactPlayer from 'react-player';
import { sliceArrByNum } from '@/utils/utils';
import CommonBorder from './Wrappers/CommonBorder';
import styles from './LiveStream.less';
import 'swiper/swiper.less';
import 'swiper/components/navigation/navigation.less';

SwiperCore.use([Navigation]);

const NoData = ({ text }) => (
  <Row className={styles.nodata} type="flex" justify="center" align="middle">
    <Col>{text}</Col>
  </Row>
);

const VideosChannel = ({ list, onClick = () => {} }) => {
  if (list.length == 0) return null;
  return (
    <div className={styles.videoChannel}>
      <div className={styles.videoChannel_selectTitle}>请选择摄像头：</div>
      <Row type="flex" justify="center" align="middle">
        {list.map(v => (
          <Col key={v.channelNo}>
            <div className={styles.swriperItem} style={{ backgroundColor: '#ffffff80' }}>
              <Row className={styles.swriperItemVideo} onClick={() => onClick(v)}>
                <Col className={styles.swriperItemVideo_cover}>
                  <div className={styles.swriperItemVideo_cover_mask} />
                  <div className={styles.swriperItemVideo_cover_imgWrapper}>
                    <img src={v.coverImg || video_cover} alt="" />
                  </div>
                </Col>
                <Col>
                  <div className={styles.swriperItemVideo_title}>{v.channelName}</div>
                </Col>
              </Row>
            </div>
          </Col>
        ))}
      </Row>
    </div>
  );
};

const VideoSwiper = ({ list = [], onClick = () => {} }) => {
  if (list.length == 0) return null;

  return (
    <Row className={styles.full_content}>
      <Row type="flex" justify="start" align="middle" className={styles.title}>
        <Col className={styles.line} />
        <Col className={styles.titleText}>附近其他驿站实时监控</Col>
      </Row>
      <Col span={24}>
        <Swiper className={styles.full_swiper} slidesPerView={5} slidesPerGroup={5} navigation>
          {list.map(v => (
            <SwiperSlide key={v.cm_id}>
              <div className={styles.swriperItem}>
                <Row className={styles.swriperItemVideo}>
                  <Col className={styles.swriperItemVideo_cover} onClick={() => onClick(v)}>
                    <div className={styles.swriperItemVideo_cover_mask} />
                    <div className={styles.swriperItemVideo_cover_imgWrapper}>
                      <img src={v.coverImg || video_cover} alt="" />
                    </div>
                  </Col>
                  <Col>
                    <div className={styles.titleText}>{v.cm_name}</div>
                  </Col>
                </Row>
              </div>
            </SwiperSlide>
          ))}
        </Swiper>
      </Col>
    </Row>
  );
};

const LiveStream = ({
  dispatch,
  currentBranchId,
  currentUserLevel,
  isParentFull,
  screenToken,
  currentLevel,
}) => {
  const [url, setUrl] = useState('');
  const [playing, setplaying] = useState(false);
  const [deviceName, setDeviceName] = useState(null);
  const [cmName, setCmName] = useState(null);
  const [channelLists, setChannelList] = useState([]);
  const [currentChannel, setCurrentChannel] = useState({});
  const [currentVideo, setCurrentVideo] = useState({});
  const [full, setFull] = useState(false);
  const [pause, setPause] = useState(false);
  const [liveId, setLiveId] = useState('');
  const [timerCount, setCount] = useState(0);
  const [loading, setLoading] = useState(false);
  const [errorInfo] = useState('该区域暂无视频监控');
  const timer = useRef(null);
  const totalCount = useRef(0);

  const prevLevel = usePrevious(currentLevel);

  // 获取驿站id
  const getYzIds = useCallback(
    async branch_id => {
      const cmids = await dispatch({
        type: 'chartData/getSubDaksList',
        payload: {
          token: screenToken,
          level: currentLevel,
          branch_id: branch_id == 0 ? 336 : branch_id, //  全国默认使用杭州市的数据
        },
      });
      return cmids.map(i => i.cm_id).join(',');
    },
    [dispatch, screenToken, currentLevel],
  );

  // 获取有视频驿站ID
  const getCmidEnableVideo = useCallback(
    async (cm_ids = '') => {
      const reqParams = cm_ids.split(',');
      const queen = sliceArrByNum(reqParams, 200);
      const res = [];

      for (let i = 0; i < queen.length; i += 1) {
        const cmid = queen[i];
        // eslint-disable-next-line no-await-in-loop
        const data = await dispatch({
          type: 'chartData/getHasVideoCmId',
          payload: {
            cm_ids: cmid.join(','),
            token: screenToken,
          },
        });
        if (data) {
          res.push(data);
        }
      }
      return res.join(',');
    },
    [dispatch, screenToken],
  );

  // 获取驿站通道
  const getChannelList = useCallback(
    cm_ids =>
      dispatch({
        type: 'chartData/getCityChannelList',
        payload: {
          token: screenToken,
          cm_ids,
        },
      }),
    [dispatch, screenToken],
  );

  // 获取播放地址
  const getVideoURL = useCallback(
    (channelData = {}) => {
      setCurrentVideo(channelData);
      return dispatch({
        type: 'chartData/getVideoURL',
        payload: {
          channel_no: channelData.channelNo,
          device_serial: channelData.deviceSerial,
          stream_index: 0,
          stream_type: 'live',
          token: screenToken,
        },
      });
    },
    [dispatch, screenToken],
  );

  // 推流播放
  const palyVideo = useCallback(
    vurl => {
      setLoading(true);
      dispatch({
        type: 'chartData/startLive',
        payload: {
          video_url: vurl,
          token: screenToken,
        },
      }).then(_liveId => {
        setLiveId(_liveId);
        setUrl(vurl.replace('http:', 'https:'));
        setplaying(true);
        setPause(false);
      });
    },
    [dispatch, screenToken],
  );

  // 关闭推流
  const closeStream = useCallback(
    unmount => {
      if (liveId) {
        setLoading(false);
        clearTimeout(timer.current);
        setCount(0);
        dispatch({
          type: 'chartData/stopLive',
          payload: {
            live_id: liveId,
            token: screenToken,
          },
        })
          .then(() => {
            if (!unmount) {
              setplaying(false);
              setUrl(null);
              setLiveId(null);
            }
          })
          .catch(err => {
            console('stop_video_err', err);
          });
      }
    },
    [liveId, dispatch, screenToken],
  );

  // 获取当前层级的通道号
  const getchannelListReady = useCallback(
    async branch_id => {
      const init_cm_ids = (await getYzIds(branch_id)) || '';
      const enable_cmids = (await getCmidEnableVideo(init_cm_ids)) || '';
      if (!enable_cmids) return;
      const _channelLists = (await getChannelList(enable_cmids)) || {};

      setChannelList(_channelLists);
      // eslint-disable-next-line consistent-return
      return _channelLists;
    },
    [getYzIds, getCmidEnableVideo, getChannelList],
  );

  const onError = useCallback(
    error => {
      console.log('error', error, moment().format('llll'));
      setUrl(null);
      // 播放失败重试
      if (timerCount >= 19) {
        setCount(0);
        totalCount.current += 1;
        // 超时停止播放
        if (totalCount.current >= 2) {
          totalCount.current = 0;
          setUrl(null);
          closeStream();
          setCurrentVideo({});
          return;
        }
        getVideoURL(currentVideo).then(vurl => {
          palyVideo(vurl);
        });
        return;
      }

      timer.current = setTimeout(() => {
        setUrl(url);
        setCount(timerCount + 1);
      }, 1000);
    },
    [timerCount, closeStream, palyVideo, getVideoURL, url, currentVideo],
  );

  const onReady = useCallback(() => {
    setplaying(true);
    setLoading(false);
    setCount(0);
    timer.current && clearTimeout(timer.current);
  }, []);

  const onPause = useCallback(() => {
    console.log('暂停');
  }, []);

  const onStart = useCallback(() => {
    console.log('播放');
    timer.current && clearTimeout(timer.current);
  }, []);

  const onVideoClick = useCallback(
    () => {
      if (!isParentFull) {
        message.warn('请在全屏下查看');
        return;
      }
      if (!full) {
        setFull(true);
      }
    },
    [full, isParentFull],
  );

  // 选择机位
  const onChangeChannel = useCallback(
    () => {
      setplaying(!playing);
      setPause(!pause);
    },
    [playing, pause],
  );

  // 切换机位
  const onChannelChange = useCallback(
    channelData => {
      closeStream();
      setDeviceName(channelData.channelName);
      getVideoURL(channelData).then(vurl => {
        palyVideo(vurl);
      });
    },
    [getVideoURL, palyVideo, closeStream],
  );

  // 切换驿站
  const onInnVideoChange = useCallback(
    ({ cm_id, cm_name, channelList, ...rest }) => {
      closeStream();
      if (cm_id) {
        const currentChannelData = channelList[0] || {};
        const currentChannelName = currentChannelData.channelName;

        setDeviceName(currentChannelName);
        setCmName(cm_name);
        setCurrentChannel({ channelList, ...rest });
        getVideoURL(currentChannelData).then(vurl => {
          palyVideo(vurl);
        });
      }
    },
    [getVideoURL, palyVideo, closeStream],
  );

  // 视频退出全屏
  const onZoomIn = useCallback(() => {
    setFull(false);
    setPause(false);
  }, []);

  // 播放视频
  useEffect(
    () => {
      if (currentLevel != prevLevel && currentLevel) {
        closeStream();
        getchannelListReady(currentBranchId).then(_channelLists => {
          if (!_channelLists) return;
          const { channelList = [], ...rest } = _channelLists[0] || {};
          const currentChannelData = channelList[0] || {};
          const currentChannelName = currentChannelData.channelName || null;
          const currentCmlName = rest.cm_name || null;

          setDeviceName(currentChannelName);
          setCmName(currentCmlName);
          setCurrentChannel({ channelList, ...rest });
          getVideoURL(currentChannelData).then(vurl => {
            palyVideo(vurl);
          });
        });
      }
    },
    [getchannelListReady, getVideoURL, palyVideo, currentBranchId, currentLevel, prevLevel],
  );

  // 卸载关闭视频
  useUnmount(() => {
    closeStream(true);
  });

  useUpdateEffect(
    () => {
      // 当大屏退出全屏时，视频自动退出全屏
      if (!isParentFull && full) {
        setFull(false);
      }
    },
    [isParentFull, full],
  );

  return (
    <CommonBorder title="实时监控" loading={loading}>
      <div
        className={classnames(styles['player-wrapper'], {
          [styles.full]: full,
          [styles.full_bg_color]: full,
        })}
        style={{
          paddingTop: full ? '' : '56.25%',
          height: '100%',
        }} /* Player ratio: 100 / (1280 / 720) */
        onClick={onVideoClick}
      >
        {full && (
          <div className={styles.selectArea}>
            <Row type="flex" align="middle" justify="space-between" className={styles.full_header}>
              <Col style={{ marginLeft: 50 }}>
                <Breadcrumb className={styles.breadcrumb}>
                  {currentUserLevel.map(v => (
                    <Breadcrumb.Item key={v.branchId}>{v.name}</Breadcrumb.Item>
                  ))}
                  {cmName && <Breadcrumb.Item key={currentChannel.cm_id}>{cmName}</Breadcrumb.Item>}
                  {deviceName && (
                    <Breadcrumb.Item key={currentChannel.channelNo}>
                      <a style={{ color: '#fff' }} onClick={onChangeChannel}>
                        {deviceName}
                      </a>
                    </Breadcrumb.Item>
                  )}
                </Breadcrumb>
              </Col>
              {!pause && (
                <Col className={styles.zoom_in}>
                  <img onClick={onZoomIn} src={zoom_in_1} alt="缩小" />
                </Col>
              )}
            </Row>
            {pause ? (
              <VideosChannel list={currentChannel.channelList} onClick={onChannelChange} />
            ) : (
              <VideoSwiper list={channelLists} onClick={onInnVideoChange} />
            )}
          </div>
        )}
        {!playing && <NoData className={styles.failed} text={errorInfo} />}
        <ReactPlayer
          style={{ cursor: !full ? 'pointer' : 'auto' }}
          className={styles['react-player']}
          width="100%"
          height="100%"
          muted
          url={url}
          playing={playing}
          onStart={onStart}
          onPause={onPause}
          onError={onError}
          onReady={onReady}
        />
      </div>
    </CommonBorder>
  );
};

export default connect(({ chartData, global }) => ({
  screenToken: global.screenToken,
  liveId: chartData.liveId,
  currentBranchId: chartData.currentAreaInfo.branchId,
  currentUserLevel: chartData.currentAreaInfo.currentUserLevel,
  currentLevel: chartData.currentAreaInfo.currentLevel,
}))(LiveStream);
